package com.koron.system.role.service.impl;

import com.auth0.jwt.interfaces.DecodedJWT;
import com.koron.bean.app.AppSimpleBean;
import com.koron.bean.base.BaseQueryBean;
import com.koron.bean.system.role.*;
import com.koron.bean.system.staff.vo.EamUser;
import com.koron.bean.util.JWTUtils;
import com.koron.bean.util.UUIDUtils;
import com.koron.common.core.business.system.SystemCacheUtil;
import com.koron.common.core.business.system.tree.TreeUtil;
import com.koron.common.core.config.ThreadLocalContext;
import com.koron.system.common.util.MenuTreeVo;
import com.koron.system.role.bean.AppMenuFunDto;
import com.koron.system.role.bean.OrgTypeTreeVo;
import com.koron.system.role.mapper.RoleMapper;
import com.koron.system.role.service.RoleService;
import com.koron.system.staff.service.StaffService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @ClassName RoleServiceImpl
 * @description
 * @Author zhouj
 * @Date 2021/7/22 14:26
 */
@Slf4j
@Service
public class RoleServiceImpl implements RoleService {

    @Autowired
    RoleMapper roleMapper;

    @Autowired
    @Lazy
    StaffService staffService;

    @Autowired
    DataSourceTransactionManager dataSourceTransactionManager;

    @Autowired
    TransactionDefinition transactionDefinition;

    @Override
    public int insertRole(EamUser user, RoleBean roleBean) {
        return roleMapper.insertRole(roleBean);
    }

    @Override
    public int updateRole(EamUser user, RoleBean roleBean) {
        return roleMapper.updateRole(roleBean);
    }

    @Override
    public int deleteRoleById(String id) {
        return roleMapper.deleteRoleById(id);
    }

    @Override
    public int deleteRoleList(List<String> ids) {
        return roleMapper.deleteRoleList(ids);
    }

    @Override
    public RoleBean querySingleRole(RoleBean roleBean) {
        return roleMapper.querySingleRole(roleBean);
    }

    @Override
    public List<RoleBean> queryRoleList(RoleBean roleBean, BaseQueryBean queryBean) {
        return roleMapper.queryRoleList(roleBean, queryBean);
    }

    @Override
    public Long queryRoleListCount(RoleBean roleBean) {
        return roleMapper.queryRoleListCount(roleBean);
    }

    @Override
    public String saveRoleJurisdiction(EamUser user, RoleJurisdictionBean roleJurisdictionBean) {

        //手动开启事务！
        TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);

        try {
            String roleId = roleJurisdictionBean.getRoleId();

            List<RoleStaffBean> roleStaffBeansPre = roleMapper.queryUserJurisdiction(roleId);

            List<AppJurisdictionBean> appJurisdictionBeanList = roleJurisdictionBean.getAppJurisdictionBeanList();
            List<RoleStaffBean> roleStaffBeanList = roleJurisdictionBean.getRoleStaffBeanList();

            List<AppSimpleBean> appList = new ArrayList<>();
            List<OrgJurisdictionBean> orgList = new ArrayList<>();
            List<MenuJurisdictionBean> menuList = new ArrayList<>();
            List<RoleStaffBean> staffList = new ArrayList<>();

            //应用权限
            appJurisdictionBeanList.forEach(p -> {
                AppSimpleBean appBean = p.getAppBean();
                String appId = appBean.getAppId();
                appBean.setRoleId(roleId);
                appBean.setId(UUIDUtils.getUuid());
                appList.add(appBean);
                //组织权限
                List<String> orgStrList = p.getOrgStrList();

                if (CollectionUtils.isNotEmpty(orgStrList)) {
                    orgStrList.forEach(o -> {
                        OrgJurisdictionBean orgJurisdictionBean = new OrgJurisdictionBean();
                        orgJurisdictionBean.setOrgId(o);
                        orgJurisdictionBean.setRoleId(roleId);
                        orgJurisdictionBean.setAppId(appId);
                        orgJurisdictionBean.setId(UUIDUtils.getUuid());
                        orgList.add(orgJurisdictionBean);
                    });
                }

                //菜单权限
                List<MenuJurisdictionBean> menuJurisdictionBeanList = p.getMenuJurisdictionBeanList();

                if (CollectionUtils.isNotEmpty(menuJurisdictionBeanList)) {
                    menuJurisdictionBeanList.forEach(m -> {
                        m.setRoleId(roleId);
                        m.setAppId(appId);
                        m.setId(UUIDUtils.getUuid());
                        menuList.add(m);
                    });
                }

            });

            if (CollectionUtils.isNotEmpty(roleStaffBeanList)) {
                roleStaffBeanList.forEach(p -> {
                    p.setRoleId(roleId);
                    p.setId(UUIDUtils.getUuid());
                    staffList.add(p);
                });
            }

            //先删除roleId关联的权限及人员组织信息
            //
            int d1 = roleMapper.deleteRoleAppByRoleId(roleId);
            int d2 = roleMapper.deleteRoleOrgByRoleId(roleId);
            int d3 = roleMapper.deleteRoleMenuByRoleId(roleId);
            int d4 = roleMapper.deleteRoleMenuFuncByRoleId(roleId);
            int d5 = roleMapper.deleteRoleStaffOrgByRoleId(roleId);

            //再添加角色权限及人员组织

            if (!CollectionUtils.isEmpty(appList)) {
                int i1 = roleMapper.insertRoleAppList(appList);
            }

            if (!CollectionUtils.isEmpty(orgList)) {
                int i2 = roleMapper.insertRoleOrgList(orgList);
            }

            if (!CollectionUtils.isEmpty(menuList)) {
                int i3 = roleMapper.insertRoleMenuList(menuList);
            }

            if (!CollectionUtils.isEmpty(staffList)) {
                int i5 = roleMapper.insertRoleStaffOrgList(staffList);
            }
            dataSourceTransactionManager.commit(transactionStatus);
            if (!CollectionUtils.isEmpty(staffList)) {

                if (!CollectionUtils.isEmpty(roleStaffBeansPre)) {
                    staffList.addAll(roleStaffBeansPre);
                }

                List<RoleStaffBean> list1 = staffList.stream().filter(p -> p.getIsOrg() == 0).collect(Collectors.toList());
                List<RoleStaffBean> list2 = staffList.stream().filter(p -> p.getIsOrg() == 1).collect(Collectors.toList());
                List<String> accountList = staffService.queryAccountByStaffOrOrgList(list1, list2);
                refreshUserInfoByAccount(accountList);
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            dataSourceTransactionManager.rollback(transactionStatus);
        }
        return null;
    }

    @Override
    public List<AppSimpleBean> queryAppJurisdiction(String roleId) {
        return roleMapper.queryAppJurisdiction(roleId);
    }

    @Override
    public List<OrgTypeTreeVo> queryOrgJurisdiction(String roleId, String appId) {
        List<OrgTypeTreeVo> orgTypeTreeVos = roleMapper.queryOrgJurisdiction(roleId, appId);
        List<OrgTypeTreeVo> tree = TreeUtil.getTree(orgTypeTreeVos);
        return tree;
    }

    @Override
    public List<MenuTreeVo> queryMenuJurisdiction(String roleId, String appId) {
        List<MenuTreeVo> list = roleMapper.queryMenuJurisdiction(roleId, appId);
        List<MenuTreeVo> treeVoList = TreeUtil.getTreeNoOrder(list);
        return treeVoList;
    }

    @Override
    public List<RoleStaffBean> queryUserJurisdiction(String roleId) {
        return roleMapper.queryUserJurisdiction(roleId);
    }

    @Override
    public RoleJurisdictionBean queryAppAllInfoJurisdiction(String roleId, String queryAppId) {

        RoleJurisdictionBean roleJurisdictionBean = new RoleJurisdictionBean();

        List<AppJurisdictionBean> appJurisdictionBeans = roleMapper.queryAppAllInfoJurisdiction(roleId, queryAppId);

        List<OrgTypeTreeVo> orgTypeTreeVos = roleMapper.queryOrgJurisdiction(roleId, queryAppId);

        Map<String, List<String>> cond1 = new HashMap<>();
        Map<String, List<MenuJurisdictionBean>> cond2 = new HashMap<>();

        //组织
        orgTypeTreeVos.forEach(p -> {

            String appId = p.getAppId();
            if (cond1.get(appId) == null) {
                List<String> orgStrList = new ArrayList<>();
                orgStrList.add(p.getId());
                cond1.put(appId, orgStrList);
            } else {
                List<String> orgTypeTreeVos1 = cond1.get(appId);
                orgTypeTreeVos1.add(p.getId());
            }
        });

        //菜单
        List<MenuJurisdictionBean> menuJurisdictionBeanList = roleMapper.queryMenuJurisdictionSimple(roleId, queryAppId);

        menuJurisdictionBeanList.forEach(p -> {
            String appId = p.getAppId();
            if (cond2.get(appId) == null) {
                List<MenuJurisdictionBean> menuTreeVoList = new ArrayList<>();
                menuTreeVoList.add(p);
                cond2.put(appId, menuTreeVoList);
            } else {
                List<MenuJurisdictionBean> menuTreeVoList = cond2.get(appId);
                menuTreeVoList.add(p);
            }
        });

        appJurisdictionBeans.forEach(p -> {

            String appId = p.getAppBean().getAppId();
            List<String> orgStrList = cond1.get(appId);
            List<MenuJurisdictionBean> menuJurisdictionBeans = cond2.get(appId);
            p.setOrgStrList(orgStrList);
            p.setMenuJurisdictionBeanList(menuJurisdictionBeans);

        });

        roleJurisdictionBean.setAppJurisdictionBeanList(appJurisdictionBeans);

        List<RoleStaffBean> roleStaffBeans = queryUserJurisdiction(roleId);
        roleJurisdictionBean.setRoleStaffBeanList(roleStaffBeans);
        roleJurisdictionBean.setRoleId(roleId);

        return roleJurisdictionBean;

    }

    @Override
    public List<RoleBean> queryUserRole(String account) {

        return roleMapper.queryUserRole(account);

    }

    @Override
    public int deleteUserRole(String account, String roleId) {

        //手动开启事务！
        TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
        int i = 0;
        try {
            i = roleMapper.deleteUserRole(account, roleId);
            dataSourceTransactionManager.commit(transactionStatus);
            refreshUserInfoByAccount(account);
            return i;
        } catch (Exception e) {
            dataSourceTransactionManager.rollback(transactionStatus);
            log.error(e.getMessage(), e);
        }

        return i;
    }

    @Override
    public int deleteUserRoleByUserIds(List<String> ids) {

        //手动开启事务！
        TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
        int i = 0;
        try {
            List<String> accountList = roleMapper.queryAccountListByUserIds(ids);
            i = roleMapper.deleteUserRoleByAccountList(accountList);
            dataSourceTransactionManager.commit(transactionStatus);
            refreshUserInfoByAccount(accountList);
            return i;
        } catch (Exception e) {
            dataSourceTransactionManager.rollback(transactionStatus);
            log.error(e.getMessage(), e);
        }

        return i;
    }

    //查询用户水司权限
    @Override
    public List<AppSimpleBean> queryAppJurisdictionByAccount(String account) {

        //查询account 下多个角色可能包含共同的水司的数据
        //role1 role2  可能都包含水司1数据,需要对水司进行分组

        List<AppSimpleBean> appSimpleBeans = new ArrayList<>();
        List<RoleBean> roleBeans = roleMapper.queryUserRoleDistinct(account, null);
        if (!CollectionUtils.isEmpty(roleBeans)) {
            List<String> roleIds = roleBeans.stream().map(RoleBean::getId).collect(Collectors.toList());
            appSimpleBeans = roleMapper.queryAppJurisdictionByRoleIds(roleIds);

        }
        return appSimpleBeans;
    }

    @Override
    public UserOwnJurisdictionBean queryUserOwnRoleJurisdiction(String account) {

        return queryUserOwnRoleJurisdictionWithRoleIds(account, null);
    }

    @Override
    public UserOwnJurisdictionBean queryUserOwnRoleJurisdictionWithRoleIds(String account, List<String> preRoleIds) {

        //查询account 下,当前水司下 多个角色可能包含共同的水司的数据
        //role1 role2  可能都包含水司1数据,需要对水司进行分组

        UserOwnJurisdictionBean userOwnJurisdictionBean = new UserOwnJurisdictionBean();
        //当前水司下的多个角色
        String currDs = ThreadLocalContext.get().getCurrDs();
        List<RoleBean> roleBeans = roleMapper.queryUserRoleDistinct(account, preRoleIds);
        if (!CollectionUtils.isEmpty(roleBeans)) {

            List<String> roleIds = roleBeans.stream().map(RoleBean::getId).collect(Collectors.toList());
            List<AppSimpleBean> appSimpleBeans = roleMapper.queryAppJurisdictionByRoleIds(roleIds);

            List<AppOrgJurisdictionBean> appOrgJurisdictionBeanList = roleMapper.queryAppOrgJurisdictionByRoleIds(roleIds);

            List<AppMenuJurisdictionBean> appMenuJurisdictionBeanList = roleMapper.queryMenuJurisdictionSimpleByRoleIds(roleIds, currDs);
            userOwnJurisdictionBean.setRoleBean(roleBeans);
            userOwnJurisdictionBean.setAppSimpleBeanList(appSimpleBeans);
            userOwnJurisdictionBean.setAppMenuJurisdictionBeanList(appMenuJurisdictionBeanList);
            userOwnJurisdictionBean.setAppOrgJurisdictionBeanList(appOrgJurisdictionBeanList);
        }
        return userOwnJurisdictionBean;
    }

    @Override
    public List<AppMenuFunDto> queryUserOwnRoleJurisdictionAll(String account) {
        List<RoleBean> roleBeans = roleMapper.queryUserRoleDistinct(account, null);
        if (!CollectionUtils.isEmpty(roleBeans)) {
            List<String> roleIds = roleBeans.stream().map(RoleBean::getId).collect(Collectors.toList());
            List<AppMenuJurisdictionBean> appMenuJurisdictionBeanList = roleMapper.queryMenuJurisdictionSimpleByRoleIds(roleIds, null);
            List<AppMenuFunDto> list = new ArrayList();
            for (AppMenuJurisdictionBean bean : appMenuJurisdictionBeanList) {
                AppMenuFunDto appMenuFunDto = new AppMenuFunDto();
                appMenuFunDto.setAppId(bean.getAppId());
                List<String> menufunlist = new ArrayList<>();
                for (MenuJurisdictionBean menuFun : bean.getMenuJurisdictionBeanList()) {
                    if (menuFun.getIsFunc().equals(1)) {
                        menufunlist.add(menuFun.getFuncId());
                    } else{
                        menufunlist.add(menuFun.getMenuId());
                    }
                }
                appMenuFunDto.setMenuAndFun(menufunlist);
                list.add(appMenuFunDto);
            }
            return list;
        }
        return new ArrayList<>();
    }

    @Override
    public int saveUserRole(String account, List<String> roleIds) {

        //手动开启事务！
        TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
        int i1 = 0;
        try {
            int i = roleMapper.deleteUserRole(account, null);
            List<RoleStaffBean> roleStaffBeans = new ArrayList<>();
            roleIds.forEach(p -> {
                RoleStaffBean roleStaffBean = new RoleStaffBean();
                roleStaffBean.setId(UUIDUtils.getUuid());
                roleStaffBean.setIsOrg(0);
                roleStaffBean.setUserOrgId(account);
                roleStaffBean.setRoleId(p);
                roleStaffBeans.add(roleStaffBean);
            });
            i1 = roleMapper.insertRoleStaffOrgList(roleStaffBeans);
            dataSourceTransactionManager.commit(transactionStatus);
            refreshUserInfoByAccount(account);
            return i1;
        } catch (Exception e) {
            dataSourceTransactionManager.rollback(transactionStatus);
            log.error(e.getMessage(), e);
        }
        return i1;
    }

    @Async
    public void refreshUserInfoByAccount(String account) {
        ArrayList<String> list = new ArrayList<>();
        list.add(account);
        refreshUserInfoByAccount(list);
    }

    @Async
    public void refreshUserInfoByAccount(List<String> accountList) {

        if (CollectionUtils.isEmpty(accountList)) {
            return;
        }
        List<EamUser> eamUsers = new ArrayList<>();
        accountList.forEach(p -> {
            EamUser redisUser = SystemCacheUtil.getRedisUser(p);
            if (Objects.isNull(redisUser)) {
                return;
            }
            EamUser eamUser = staffService.queryStaffInfo(p);
            if (eamUser != null) {
                eamUsers.add(eamUser);
            }
        });
        refreshUserInfo(eamUsers);
    }

    @Async
    public void refreshUserInfo(List<EamUser> eamUserList) {
        eamUserList.forEach(p -> {
            String account = p.getAccount();
            EamUser redisUser = SystemCacheUtil.getRedisUser(account);
            if (!Objects.isNull(redisUser)) {
                List<String> userTokenList = new ArrayList<>();
                List<String> tokenList = redisUser.getTokenList();
                if (CollectionUtils.isNotEmpty(tokenList)) {
                    for (String u : tokenList) {
                        DecodedJWT verify = JWTUtils.verify(u);
                        if (verify != null) {
                            userTokenList.add(u);
                        }
                    }
                }
                p.setTokenList(userTokenList);
                SystemCacheUtil.cacheUserInfo(p);
            }
        });
    }

}
